2. 컨테이너 살펴보기
1. 가벼운 실습: Ubuntu 22.04 컨테이너 실행
실습 목표
도커를 사용하여 Ubuntu 22.04 이미지를 pull하고 컨테이너로 실행해보기
용어 정리
- pull: 레지스트리(저장소)에서 이미지를 로컬로 다운로드하는 동작
- 이미지 (Image): 컨테이너 실행에 필요한 파일과 설정을 담은 읽기 전용 템플릿. 컨테이너의 "설계도"
- 컨테이너 (Container): 이미지를 기반으로 실행된 프로세스. 이미지의 "실행 인스턴스"
기본 명령어
컨테이너 기본 작업 흐름:
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
[이미지 다운로드]
↓
docker pull ubuntu:22.04
↓
[컨테이너 실행]
↓
docker run -it ubuntu:22.04
↓
[컨테이너 내부에서 작업]
2. 기본적인 컨테이너 기술의 특징
컨테이너 기술의 3대 특징:
컨테이너 핵심 가치:
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
[컨테이너 기술]
│
├─→ 1. 가벼운 실행 환경
│ └─ 프로세스 수준 격리
│ └─ 빠른 시작/종료
│
├─→ 2. 높은 이식성
│ └─ 동작 재현성
│ └─ 표준 규격
│
└─→ 3. 거대한 생태계
└─ OCI/CNCF
└─ 다양한 도구
2.1. 가벼운 실행 환경
가상머신 vs 컨테이너
실행 환경 구조 비교:
[가상머신 (Virtual Machine)]
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
┌────────────────────────────┐
│ 애플리케이션 + 라이브러리 │
├────────────────────────────┤
│ 게스트 OS (Linux) │
├────────────────────────────┤
│ 하이퍼바이저 (KVM) │
├────────────────────────────┤
│ 호스트 OS (Linux) │
├────────────────────────────┤
│ 물리 하드웨어 │
└────────────────────────────┘
특징:
• OS 전체를 가상화
• 부팅 시간: 수십 초~분
• 크기: 수 GB
• 격리: 매우 강력
[컨테이너 (Container)]
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
┌────────────────────────────┐
│ 애플리케이션 + 라이브러리 │
├────────────────────────────┤
│ 컨테이너 런타임 (Docker) │
├────────────────────────────┤
│ 호스트 OS (Linux) │
│ (네임스페이스 격리) │
├────────────────────────────┤
│ 물리 하드웨어 │
└────────────────────────────┘
특징:
• 프로세스 수준 가상화
• 시작 시간: 수 초 이내
• 크기: 수십 MB~수백 MB
• 격리: OS 커널 공유
가상머신의 동작 원리
하이퍼바이저 기반 가상화:
가상머신은 AWS, Azure 등 대표적인 클라우드 서비스에서 주요 실행 환경으로 제공됨
가상머신 구조:
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
[물리 서버]
↓
[하이퍼바이저]
├─ 가상 하드웨어 제공
├─ 자원 할당 관리
└─ OS 간 격리
↓
┌────┬────┬────┐
│VM 1│VM 2│VM 3│
│OS A│OS B│OS C│
└────┴────┴────┘
장점:
✓ 완전한 OS 격리
✓ 다양한 OS 동시 실행
✓ 강력한 보안
단점:
✗ 무거운 리소스 사용
✗ 느린 시작 속도
✗ OS 라이선스 필요
하이퍼바이저 계층의 역할
하이퍼바이저는 하드웨어와 OS 사이에 위치한 관리 계층으로, 가상화의 핵심 역할을 수행함
하이퍼바이저 동작 원리:
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
[물리 하드웨어]
│
├─ CPU
├─ 메모리
├─ 디스크
└─ 네트워크
↓
[하이퍼바이저 계층]
│
├─ 하드웨어 추상화
│ └─ 물리 자원을 가상 자원으로 변환
│
├─ 자원 할당 및 스케줄링
│ └─ VM별 CPU, 메모리, 디스크 할당
│
├─ VM 격리
│ └─ VM 간 독립성 보장
│
└─ 가상 하드웨어 제공
└─ 각 VM에게 독립된 하드웨어처럼 보이게 함
↓
[게스트 OS들]
↓
각 VM은 독립된 물리 머신처럼 동작
핵심:
→ 하이퍼바이저 = 가상화 관리자
→ 하드웨어를 소프트웨어로 에뮬레이션
하이퍼바이저 타입
하이퍼바이저 분류:
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
[Type 1 - Bare Metal (Native)]
┌────────────────────┐
│ VM 1 │ VM 2 │
├────────────────────┤
│ 하이퍼바이저 │
├────────────────────┤
│ 물리 하드웨어 │
└────────────────────┘
특징:
• 하드웨어 위에 직접 설치
• 높은 성능
• 서버 가상화에 적합
예시:
├─ VMware ESXi
├─ Microsoft Hyper-V
├─ KVM (Kernel-based Virtual Machine)
└─ Xen
[Type 2 - Hosted]
┌────────────────────┐
│ VM 1 │ VM 2 │
├────────────────────┤
│ 하이퍼바이저 │
├────────────────────┤
│ 호스트 OS │
├────────────────────┤
│ 물리 하드웨어 │
└────────────────────┘
특징:
• 기존 OS 위에서 실행
• 설치/사용 간편
• 데스크톱 가상화에 적합
예시:
├─ VMware Workstation
├─ Oracle VirtualBox
└─ Parallels Desktop
실무:
→ Type 1: 데이터센터, 클라우드
→ Type 2: 개발자 로컬 환경
활용 사례:
- 서버 통합 (Server Consolidation)
- 클라우드 인프라 (AWS EC2, Azure VM)
- 개발/테스트 환경
컨테이너의 동작 원리
OS 커널 공유 방식:
컨테이너는 호스트 OS 커널을 기반으로 환경 격리 기능을 활용하여 독립적인 실행 환경을 만듦
OS 커널이란?
OS 커널 (Kernel):
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
[정의]
운영체제의 핵심 구성 요소로,
하드웨어와 애플리케이션 사이에서
자원을 관리하고 중재하는 계층
[OS 전체 구조]
┌──────────────────────┐
│ 애플리케이션 영역 │
│ (User Space) │
├──────────────────────┤
│ 시스템 라이브러리 │
│ (libc, glibc 등) │
├──────────────────────┤
│ 커널 영역 │
│ (Kernel Space) │
│ ┌────────────────┐ │
│ │ 프로세스 관리 │ │
│ │ 메모리 관리 │ │
│ │ 파일시스템 │ │
│ │ 네트워크 스택 │ │
│ │ 디바이스 드라이버│ │
│ └────────────────┘ │
├──────────────────────┤
│ 물리 하드웨어 │
└──────────────────────┘
커널의 주요 역할:
├─ 프로세스 관리
│ └─ 프로세스 생성, 종료, 스케줄링
│
├─ 메모리 관리
│ └─ 메모리 할당, 해제, 가상 메모리
│
├─ 파일시스템 관리
│ └─ 파일 읽기/쓰기, 권한 관리
│
├─ 네트워크 관리
│ └─ 네트워크 통신, 프로토콜 스택
│
└─ 디바이스 관리
└─ 하드웨어 추상화, 드라이버 인터페이스
핵심:
→ 커널 = OS의 뇌
→ 시스템 자원의 문지기
→ 하드웨어 접근의 중재자
컨테이너가 커널을 공유하는 방식
컨테이너 격리 메커니즘:
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
[호스트 OS 커널]
│
├─ Namespace (격리)
│ ├─ PID: 프로세스 격리
│ ├─ NET: 네트워크 격리
│ ├─ MNT: 파일시스템 격리
│ ├─ UTS: 호스트명 격리
│ └─ IPC: 프로세스 간 통신 격리
│
└─ Cgroups (자원 제한)
├─ CPU 사용량
├─ 메모리 사용량
└─ 디스크 I/O
↓
┌──────────┬──────────┬──────────┐
│컨테이너 1 │컨테이너 2 │컨테이너 3 │
│독립 환경 │독립 환경 │독립 환경 │
└──────────┴──────────┴──────────┘
모든 컨테이너가 동일한 커널 공유
→ 가볍고 빠른 시작
→ 호스트와 동일한 커널 버전 사용
Namespace와 Cgroups 상세
리눅스 커널의 격리 기능:
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
[Namespace - 격리 기능]
각 컨테이너에게 독립된 환경을 제공
PID Namespace:
├─ 컨테이너마다 독립된 프로세스 ID 공간
├─ 컨테이너 내부: PID 1부터 시작
└─ 다른 컨테이너 프로세스 불가시
NET Namespace:
├─ 독립된 네트워크 인터페이스
├─ 자체 IP 주소, 라우팅 테이블
└─ 포트 충돌 없음
MNT Namespace:
├─ 독립된 파일시스템 마운트
├─ 자체 루트 디렉토리 (/)
└─ 호스트 파일시스템과 분리
UTS Namespace:
├─ 독립된 호스트명
└─ 도메인명 설정
IPC Namespace:
├─ 독립된 프로세스 간 통신
└─ 공유 메모리, 세마포어 격리
[Cgroups - 자원 제한]
컨테이너의 자원 사용을 제한
CPU Cgroup:
└─ 컨테이너당 CPU 사용률 제한
예: "최대 2 코어만 사용"
Memory Cgroup:
└─ 컨테이너당 메모리 제한
예: "최대 1GB RAM 사용"
Block I/O Cgroup:
└─ 디스크 읽기/쓰기 속도 제한
예: "최대 100MB/s"
Network Cgroup:
└─ 네트워크 대역폭 제한
결과:
→ Namespace = "무엇을 볼 수 있는가"
→ Cgroups = "얼마나 사용할 수 있는가"
컨테이너 격리 특징
컨테이너의 격리 수준:
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
[컨테이너 내부에서 보는 세계]
│
├─ 독립된 루트 파일시스템
│ └─ /bin, /etc, /lib 등
│
├─ 격리된 프로세스 공간
│ └─ 다른 컨테이너 프로세스 불가시
│
├─ 독립된 네트워크
│ └─ 자체 IP, 포트
│
└─ 호스트 자원 제한
└─ CPU, 메모리 제한
핵심:
→ OS 커널 포함 X
→ 프로세스로 실행
→ 마치 독립 OS처럼 동작
가상머신 vs 컨테이너 비교
| 구분 | 가상머신 | 컨테이너 |
|---|---|---|
| 가상화 대상 | 하드웨어 | OS 커널 |
| OS | 게스트 OS 포함 | 호스트 OS 공유 |
| 시작 속도 | 느림 (분) | 빠름 (초) |
| 크기 | 큰 편 (GB) | 작음 (MB) |
| 자원 사용 | 많음 | 적음 |
| 격리 수준 | 강력 | 중간 |
| 이식성 | 보통 | 높음 |
| 용도 | 완전한 OS 환경 필요 | 애플리케이션 배포 |
2.2. 높은 이식성
컨테이너 이미지의 동작 재현성
이식성의 핵심 원리:
컨테이너 이미지 이식성:
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
[개발 환경]
↓
[컨테이너 이미지 빌드]
├─ 애플리케이션 코드
├─ 의존 라이브러리
├─ 런타임 환경
└─ 설정 파일
↓
[이미지를 레지스트리에 푸시]
↓
[다른 환경에서 Pull]
↓
┌────────┬────────┬────────┐
│개발 PC │테스트 │프로덕션│
│환경 │서버 │서버 │
└────────┴────────┴────────┘
↓
동일한 동작 보장
장점:
✓ "내 컴퓨터에서는 되는데..." 문제 해결
✓ 환경 차이로 인한 버그 최소화
✓ 빠른 배포
라이브러리 버전 불일치 해결
전통적 배포 방식의 문제:
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
[개발 환경]
Python 3.9
Django 4.0
PostgreSQL 13
↓
[프로덕션 서버]
Python 3.8 ← 버전 차이!
Django 3.2 ← 호환성 문제!
PostgreSQL 12
↓
[애플리케이션 오류]
컨테이너 방식:
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
[컨테이너 이미지]
├─ Python 3.9
├─ Django 4.0
├─ PostgreSQL 13
└─ 모든 의존성 포함
↓
[어디서나 동일하게 실행]
↓
환경 불일치 문제 해결
업계 표준 규격
컨테이너 표준 작업 흐름:
컨테이너 작업 흐름:
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
1. Build (빌드)
└─ Dockerfile로 이미지 생성
↓
2. Ship (공유)
└─ 레지스트리에 이미지 푸시
↓
3. Run (실행)
└─ 컨테이너 런타임으로 실행
이 세 단계가 표준화됨
컨테이너 기술 스택
컨테이너 표준 기술 스택:
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
[빌드 도구]
├─ Docker Build
├─ Buildah
└─ Kaniko
[레지스트리]
├─ Docker Hub
├─ AWS ECR
├─ Google GCR
└─ Harbor
[컨테이너 런타임]
├─ Docker Engine
├─ containerd
├─ CRI-O
└─ Podman
모두 OCI 표준 준수
→ 상호 호환 가능
2.3. 거대한 생태계
Open Container Initiative (OCI)
용어 정리
- OCI (Open Container Initiative): 2015년 Docker, CoreOS, Google 등이 설립한 오픈소스 프로젝트. 컨테이너 기술의 표준 규격을 정의하여 벤더 종속성을 방지
- Spec (Specification): 규격/명세서. 소프트웨어가 따라야 하는 표준 정의 문서
OCI의 역할:
OCI (Open Container Initiative):
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
[리눅스 재단 산하]
↓
[OCI 프로젝트]
│
├─→ 이미지 규격 (Image Spec)
│ └─ 컨테이너 이미지 형식 정의
│
├─→ 런타임 규격 (Runtime Spec)
│ └─ 컨테이너 실행 방법 정의
│
└─→ 배포 규격 (Distribution Spec)
└─ 레지스트리 동작 방식 정의
결과:
→ 다양한 도구 간 상호 운용성
→ 벤더 종속성 감소
→ 생태계 확장
Cloud Native Computing Foundation (CNCF)
용어 정리
- CNCF (Cloud Native Computing Foundation): 클라우드 네이티브 오픈소스 프로젝트를 관리하는 Linux Foundation 산하 재단. Kubernetes, Prometheus, Envoy 등을 관리
- Cloud Native: 클라우드 환경에 최적화된 애플리케이션 개발/운영 방식. 컨테이너, 마이크로서비스, CI/CD, 오케스트레이션 등을 활용
- Graduated/Incubating/Sandbox: CNCF 프로젝트 성숙도 등급. Sandbox(초기) → Incubating(성장) → Graduated(성숙)
CNCF 프로젝트 성숙도:
CNCF 프로젝트 단계:
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
[Graduated - 졸업]
├─ Kubernetes
├─ Prometheus
├─ Envoy
├─ containerd
└─ Helm
↓
가장 성숙하고 널리 사용됨
프로덕션 환경 권장
[Incubating - 인큐베이팅]
├─ etcd
├─ CoreDNS
└─ Argo
↓
안정화 단계
활발히 개발 중
[Sandbox - 샌드박스]
└─ 초기 단계 프로젝트
↓
실험적 기술
쿠버네티스 관련 표준
용어 정리:
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
[Interface (인터페이스)]
│
└─ 서로 다른 시스템이 소통하는 방식을 정의한 규약
"이 규칙만 따르면 어떤 구현체든 연결 가능"
[플러그인 (Plugin)]
│
└─ 기본 시스템에 기능을 추가하는 확장 모듈
표준 인터페이스를 따르면 쉽게 교체 가능
[deprecated]
│
└─ 더 이상 권장되지 않음, 향후 제거 예정
새 프로젝트에서는 사용 자제
쿠버네티스 플러그인 인터페이스:
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
[CRI - Container Runtime Interface]
└─ 컨테이너 런타임 플러그인
├─ containerd
├─ CRI-O
└─ Docker (deprecated)
[CSI - Container Storage Interface]
└─ 스토리지 플러그인
├─ AWS EBS
├─ Ceph
└─ NFS
[CNI - Container Network Interface]
└─ 네트워크 플러그인
├─ Calico
├─ Flannel
└─ Cilium
표준화된 인터페이스
→ 다양한 구현체
→ 선택의 자유
3. 이 책에서 다루는 도커와 쿠버네티스
도커 (Docker)
도커의 역할:
도커 기능:
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
[단일 머신 컨테이너 관리]
│
├─→ 컨테이너 실행/중지
│ └─ docker run, docker stop
│
├─→ 이미지 빌드
│ └─ Dockerfile 기반 빌드
│
├─→ 이미지 공유
│ └─ Docker Hub, Registry
│
└─→ 네트워크/볼륨 관리
└─ 로컬 개발 환경
핵심 가치:
→ 컨테이너 기술 대중화
→ 간단한 작업 흐름 제공
→ 개발자 친화적
도커의 영향
도커는 도구 자체의 편의성뿐만 아니라 컨테이너 기본 조작을 간단한 작업 흐름(Build, Ship, Run)으로 업계에 전파하여 컨테이너 기술 확산에 큰 역할을 함
쿠버네티스 (Kubernetes)
쿠버네티스의 역할:
쿠버네티스 기능:
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
[다중 머신 컨테이너 오케스트레이션]
│
├─→ 자가 치유 (Self-Healing)
│ └─ 노드 장애 시 자동 재시작
│
├─→ 오토 스케일링
│ └─ 부하에 따라 자동 확장/축소
│
├─→ 로드 밸런싱
│ └─ 트래픽 분산
│
├─→ 롤링 업데이트
│ └─ 무중단 배포
│
└─→ 선언적 관리
└─ 매니페스트 기반 인프라 관리
대상:
→ 프로덕션 환경
→ 대규모 시스템
선언적 관리 스타일
쿠버네티스 선언적 관리:
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
[매니페스트 작성 (YAML)]
↓
원하는 상태 정의:
"이 애플리케이션은
3개의 복제본으로 실행되어야 함"
↓
[kubectl apply]
↓
[쿠버네티스가 자동으로 현재 상태를 원하는 상태로 조정]
↓
┌────────┬────────┬────────┐
│ Pod 1 │ Pod 2 │ Pod 3 │
└────────┴────────┴────────┘
장점:
✓ 인프라를 코드로 관리
✓ 버전 관리 가능
✓ 재현 가능
✓ 자동화
명령형 vs 선언형 비교
관리 방식 비교:
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
[명령형 (Imperative)]
"컨테이너 3개를 시작해"
"컨테이너 1개를 중지해"
"포트 80을 열어"
↓
단계별 명령 실행
↓
✗ 복잡한 조작 필요
✗ 현재 상태 파악 어려움
[선언형 (Declarative)]
"최종 상태는 이것이다"
replicas: 3
port: 80
↓
쿠버네티스가 알아서 조정
↓
✓ 단순한 관리
✓ 자가 치유
✓ GitOps 가능
컨테이너 런타임
컨테이너 런타임의 역할
컨테이너 런타임:
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
[정의]
관리 도구의 지시를 받아
머신에서 컨테이너를 직접 작성하고
관리하는 저수준 소프트웨어
[역할]
↓
[도커/쿠버네티스]
│ 명령
↓
[컨테이너 런타임]
├─ Namespace 생성
├─ Cgroups 설정
├─ 파일시스템 마운트
└─ 프로세스 실행
↓
[컨테이너 프로세스]
숨은 실력자:
→ 컨테이너를 컨테이너답게 만드는 핵심
컨테이너 런타임 계층
컨테이너 런타임 구조:
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
[High-level Runtime]
├─ Docker Engine
├─ containerd
└─ CRI-O
│
↓ OCI 표준 호출
│
[Low-level Runtime]
└─ runc (OCI 참조 구현)
│
↓
[Linux Kernel]
├─ Namespace
├─ Cgroups
└─ Capabilities
도커와 쿠버네티스의 런타임 사용
런타임 사용 관계:
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
[도커]
↓
[Docker Engine]
↓
[containerd]
↓
[runc]
[쿠버네티스]
↓
[CRI 플러그인]
↓
[containerd / CRI-O]
↓
[runc]
쿠버네티스 자체는
컨테이너 생성 기능 없음
→ 각 노드의 런타임이 담당
핵심 요약
컨테이너 기술 요약:
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
[컨테이너]
├─ 가벼운 실행 환경
│ └─ OS 커널 공유, 프로세스 격리
│
├─ 높은 이식성
│ └─ 이미지 기반 배포, 표준 규격
│
└─ 거대한 생태계
└─ OCI, CNCF, 다양한 도구
[도커]
└─ 단일 머신 컨테이너 관리
└─ Build, Ship, Run
[쿠버네티스]
└─ 다중 머신 오케스트레이션
└─ 자동화, 확장성, 고가용성
[컨테이너 런타임]
└─ 실제 컨테이너 실행
└─ runc, containerd, CRI-O
결론:
→ 컨테이너 = 현대 애플리케이션 배포 표준
→ 도커 = 개발 및 로컬 환경
→ 쿠버네티스 = 프로덕션 환경
참고 자료
공식 문서:
- Docker Overview: https://docs.docker.com/get-started/overview/
- Docker Run Reference: https://docs.docker.com/engine/reference/run/
- Docker CLI Reference: https://docs.docker.com/engine/reference/commandline/cli/
관련 주제:
- 컨테이너 vs 가상 머신: https://www.docker.com/resources/what-container/
- OCI (Open Container Initiative): https://opencontainers.org/